package ocio.actions;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import ocio.beans.Oferta;
import ocio.beans.Producto;
import ocio.beans.Provincia;
import ocio.beans.Subtipo;
import ocio.services.ProductoService;
import ocio.services.ProvinciaService;
import ocio.services.ServiceLocator;
import ocio.services.SubtipoService;
import ocio.utils.Constantes;
import ocio.utils.RellenoCombos;
import com.opensymphony.xwork2.ActionSupport;

/**
 * Clase destinataria de petición de búsqueda de ofertas que cumplan
 * las características especificadas en un formulario. Es llamada cada vez que 
 * el usuario cambia alguno de los criterios de búsqueda.
 * @author Esther García Galán
 * @author Rubén Gómez Vales
 * @version 1.0 13/05/2014
 * @see ocio.beans.Cliente
 */
public class BuscarOfertaAction extends ActionSupport {
	
	private static final long serialVersionUID = 1L;
	private String tipo;
	private int idProv;
	private int idSubtipo;
	private String municipio = "Todas";
	private Set<String> listaMunicipios = new HashSet<String>();
	private List<Subtipo> listaSubtipos = new ArrayList<Subtipo>();
	private List<Producto> listaProductos = new ArrayList<Producto>();
	private boolean sinOfertas = false;
	private String cuando = "any";   
	private int dia;
	private int mes;
	private int anio;
	private List<Integer> listaMeses;
	private List<Integer> listaDias;
	private List<Integer> listaAnios;
	private String mensaje = "";
	private List<String> listaNumPlazas = Constantes.getListaNumPlazas();
	private List<String> listaPrecios = Constantes.getListaPrecios();
	private int numPlazas = 1;
	private String precioT = "Todos";
	private String msgSinOfertas ="";
	
	
	public BuscarOfertaAction(){}

	  /**
	 * Método execute() de la clase ActionSupport de Struts 2. 
	 * Solicita los servicios para localizar los productos con alguna oferta que se ajuste 
	 * a los criterios de búsqueda establecidos en el formulario. Busca productos por tipo, subtipo,
	 * provincia y municipio y luego aplica a sus ofertas el filtro por fecha, plazas disponibles y precio.
	 * @return un string que indica la respuesta de la acción ejecutada sobre la petición del usuario
	 */
	public String execute(){
		
		ServiceLocator serviceLocator = ServiceLocator.getServiceLocator();
		RellenoCombos rC = new RellenoCombos();
	
		//Prepara el combo subtipo
		Subtipo subtipo = new Subtipo();
		subtipo.setNombre("Lo que sea...");
		listaSubtipos.add(subtipo);
		listaSubtipos.addAll(rC.getListaSubtipos(tipo));
		
		
		// Prepara el combo municipios
		listaMunicipios.add("Todas");
		listaMunicipios.addAll(rC.getListaMunicipios(idProv, tipo, idSubtipo));
		if (listaMunicipios.size()==1&&idProv!=0){
			sinOfertas = true;
		}
		
		ProductoService prodS = (ProductoService)serviceLocator.getService("Producto");
		ProvinciaService provS = (ProvinciaService)serviceLocator.getService("Provincia");
		SubtipoService subtipoS = (SubtipoService)serviceLocator.getService("Subtipo");
		
		// Busca lista resultados con los criterios fijados
		if ((sinOfertas)!=true){
	
			Producto producto = new Producto();
			
			//Añadimos criterio tipo
			producto.setTipo(rC.getTipoInt(tipo));
			
			//Añadimos criterio subtipo
			subtipo = (Subtipo)subtipoS.searchById(idSubtipo);
			if (subtipo!=null){
				producto.setSubtipo(subtipo);
			}
						
			//Añadimos criterio de provincia
			if (idProv!=0){
				Provincia provincia = (Provincia) provS.searchById(idProv);
				producto.setProvincia(provincia);
			} else {				
				producto.setProvincia(null);
			}
			
			// Añadimos criterio de municipio:
			if (idProv!=0&&!municipio.equals("Todas")){
				producto.setMunicipio(municipio);
			}
			
			Iterator<Object> itr = prodS.searchByFields(producto).iterator();

			Producto candidato = new Producto();
			Date hoy = new Date();
			Date fechaBusqueda = new Date();
			SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
			
			if (cuando.equals("dia")) {
				try { //Comprobar si la fecha es válida
					fechaBusqueda=sdf.parse(dia + "/" + mes + "/" + anio);
				} catch (ParseException e) {
					setMensaje("Error en el formato de fecha.");
				return "input";
				}
			}
			
			while (itr.hasNext()){
				candidato = (Producto)itr.next();
				Iterator<Oferta> itOferta = candidato.getOfertas().iterator();
				while (itOferta.hasNext()){
					Oferta oferta =(Oferta)itOferta.next();
					// Filtramos criterio precio 
					if ((oferta.getPrecioXpersona()<getPrecio(precioT))){
						// Se filtra que haya suficientes plazas disponibles
						if (numPlazas <= (oferta.getPlazasDisp()-oferta.getPlazasReserv())){
							
							// Filtro para que esté en rango de fechas seleccion
							// Caso espectáculos la fecha limite es la del espectaculo. 
							// y debe coincidir con la de búsqueda
							if((cuando.equals("dia"))&&(candidato.getTipo()==2)){
								if(oferta.getFechaLim().compareTo(fechaBusqueda)==0){
									listaProductos.add(candidato);
									break;
								} 
							
							// Resto de casos la limite debe ser posterior a la de búsqueda	
							// y esta posterior a la fecha actual new Date.
							} else if ((!fechaBusqueda.before(hoy))&&(!fechaBusqueda.after(oferta.getFechaLim()))){
									listaProductos.add(candidato);
									break;
							}
							

						}

					}
				}
			}
			
			if (listaProductos.size()==0){
				setMsgSinOfertas("No se han encontrado ofertas para sus criterios de búsqueda");
			}

		}
		
		// Prepara el combo fecha si ha cambiado
		setListaMeses(Constantes.getListameses());
		setListaAnios(Constantes.getListaAnios());
		switch (mes){
				case 0: case 1: case 3: case 5: case 7:
				case 8: case 10: case 12:
					setListaDias(Constantes.getListaDias(31));
					break;
				case 4: case 6: case 9: case 11:
					setListaDias(Constantes.getListaDias(30));
					break;
				case 2:
					setListaDias(Constantes.getListaDias(28));				
					break;
		}
		if (listaProductos.size()==0){
			setMsgSinOfertas("No se han encontrado ofertas para sus criterios de búsqueda");
		} 		
		return "success";
	}
	
	public String getTipo() {
		return tipo;
	}

	public void setTipo(String tipo) {
		this.tipo = tipo;
	}

	public Set<String> getListaMunicipios() {
		return listaMunicipios;
	}

	public void setListaMunicipios(Set<String> listaMunicipios) {
		this.listaMunicipios = listaMunicipios;
	}

	public int getIdSubtipo() {
		return idSubtipo;
	}

	public void setIdSubtipo(int idSubtipo) {
		this.idSubtipo = idSubtipo;
	}
	public int getIdProv() {
		return idProv;
	}

	public void setIdProv(int idProv) {
		this.idProv = idProv;
	}

	public List<Subtipo> getListaSubtipos() {
		return listaSubtipos;
	}

	public void setListaSubtipos(List<Subtipo> listaSubtipos) {
		this.listaSubtipos = listaSubtipos;
	}

	public List<Producto> getListaProductos() {
		return listaProductos;
	}

	public void setListaProductos(List<Producto> listaProductos) {
		this.listaProductos = listaProductos;
	}

	public String getMunicipio() {
		return municipio;
	}

	public void setMunicipio(String municipio) {
		this.municipio = municipio;
	}

	public int getDia() {
		return dia;
	}

	public void setDia(int dia) {
		this.dia = dia;
	}

	public int getMes() {
		return mes;
	}

	public void setMes(int mes) {
		this.mes = mes;
	}

	public int getAnio() {
		return anio;
	}

	public void setAnio(int anio) {
		this.anio = anio;
	}

	public String getCuando() {
		return cuando;
	}

	public void setCuando(String cuando) {
		this.cuando = cuando;
	}

	public List<Integer> getListaMeses() {
		return listaMeses;
	}

	public void setListaMeses(List<Integer> listaMeses) {
		this.listaMeses = listaMeses;
	}

	public List<Integer> getListaDias() {
		return listaDias;
	}

	public void setListaDias(List<Integer> listaDias) {
		this.listaDias = listaDias;
	}

	public List<Integer> getListaAnios() {
		return listaAnios;
	}

	public void setListaAnios(List<Integer> listaAnios) {
		this.listaAnios = listaAnios;
	}

	public String getMensaje() {
		return mensaje;
	}

	public void setMensaje(String mensaje) {
		this.mensaje = mensaje;
	}

	public List<String> getListaNumPlazas() {
		return listaNumPlazas;
	}

	public void setListaNumPlazas(List<String> listaNumPlazas) {
		this.listaNumPlazas = listaNumPlazas;
	}

	public int getNumPlazas() {
		return numPlazas;
	}

	public void setNumPlazas(int numPlazas) {
		this.numPlazas = numPlazas;
	}

	public List<String> getListaPrecios() {
		return listaPrecios;
	}

	public void setListaPrecios(List<String> listaPrecios) {
		this.listaPrecios = listaPrecios;
	}

	public String getPrecioT() {
		return precioT;
	}

	public void setPrecioT(String precioT) {
		this.precioT = precioT;
	}

	private double getPrecio(String precioT){
		double precio = 100000.0;
		if (precioT.length()>6){
			precio = Double.parseDouble(precioT.substring(2, 4));
		}
		return precio;
		
		
	}

	public String getMsgSinOfertas() {
		return msgSinOfertas;
	}

	public void setMsgSinOfertas(String msgSinOfertas) {
		this.msgSinOfertas = msgSinOfertas;
	}

	
}
